package com.polytech.diploma.SQLGenerator.Oracle.Statements;

import java.util.List;
import java.util.Map;

import com.polytech.diploma.SQLGenerator.Oracle.Arguments.Argument;
import com.polytech.diploma.SQLGenerator.Oracle.Arguments.Field;
import com.polytech.diploma.SQLGenerator.Oracle.Conditions.Condition;
import com.polytech.diploma.SQLGenerator.Oracle.Functions.Function;
import com.polytech.diploma.SQLGenerator.Oracle.Statements.OrderByClause.OrderByClause;

public class Table implements Subquery {
	
	protected String name;
	protected String alias;
	
	/**
	 * Alias + field
	 */
	protected Map<Field, String> fields = null;	
	
	/**
	 * Alias + function
	 */
	protected Map<Function, String> functions = null;
	
	/**
	 * The root of WHERE Clause
	 */
	protected Condition conditions = null;
	
	protected List<Argument> groupByClause = null;
	protected List<OrderByClause> orderByArgs = null;
	
	protected HierarchicalClause hierarchicalClause;
	protected Subquery subquery;
	
	public Map<String, List<String>> getTablesWithFields(Map<String, List<String>> fieldMap)
	{
		if(fields != null)
			for(Field field : fields.keySet())
			{
				fieldMap = field.getTablesWithFields(fieldMap);
			}
		
		if(functions != null)
			for(Function function : functions.keySet())
			{
				fieldMap = function.getTablesWithFields(fieldMap);
			}
		
		if(conditions != null)
			fieldMap = conditions.getTablesWithFields(fieldMap);
		
		if(groupByClause != null)
			for(Argument arg: groupByClause)
			{
				fieldMap = arg.getTablesWithFields(fieldMap);
			}
		
		if(orderByArgs != null)
			for(OrderByClause orderByArg: orderByArgs)
			{
				fieldMap = orderByArg.getTablesWithFields(fieldMap);
			}
		
		if(hierarchicalClause != null)
			fieldMap = hierarchicalClause.getTablesWithFields(fieldMap);
		if(subquery != null)
			fieldMap = subquery.getTablesWithFields(fieldMap);
		
		return fieldMap;
	}

	private Table(Builder builder) {
		super();
		this.name = builder.name;
		this.alias = builder.alias;
		this.fields = builder.fields;
		this.functions = builder.functions;
		this.conditions = builder.conditions;
		this.groupByClause = builder.groupByClause;
		this.orderByArgs = builder.orderByArgs;
		this.hierarchicalClause = builder.hierarchicalClause;
		this.subquery = builder.subquery;
	}

	public static class Builder
	{
		private String name;
		private String alias;
		private Map<Field, String> fields = null;
		private Map<Function, String> functions = null;
		private Condition conditions = null;		
		private List<Argument> groupByClause = null;
		private List<OrderByClause> orderByArgs = null;
		private HierarchicalClause hierarchicalClause;
		private Subquery subquery;
		
		public Builder setName(String name) {
			this.name = name;
			return this;
		}
		public Builder setAlias(String alias) {
			this.alias = alias;
			return this;
		}
		public Builder setFields(Map<Field, String> fields) {
			this.fields = fields;
			return this;
		}
		public Builder setFunctions(Map<Function, String> functions) {
			this.functions = functions;
			return this;
		}
		public Builder setConditions(Condition conditions) {
			this.conditions = conditions;
			return this;
		}
		public Builder setGroupByClause(List<Argument> groupByClause) {
			this.groupByClause = groupByClause;
			return this;
		}
		public Builder setOrderByClause(List<OrderByClause> orderByArgs) {
			this.orderByArgs = orderByArgs;
			return this;
		}
		public Builder setHierarchicalClause(HierarchicalClause hierarchicalClause) {
			this.hierarchicalClause = hierarchicalClause;
			return this;
		}
		public Builder setSubquery(Subquery subquery) {
			this.subquery = subquery;
			return this;
		}
		public Table build()
		{
			return new Table(this);
		}
	}

	public String getName() {
		return name;
	}

	public String getAlias() {
		return alias;
	}

	public Map<Field, String> getFields() {
		return fields;
	}

	public Map<Function, String> getFunctions() {
		return functions;
	}

	public Condition getConditions() {
		return conditions;
	}

	public List<Argument> getGroupByClause() {
		return groupByClause;
	}

	public List<OrderByClause> getOrderByArgs() {
		return orderByArgs;
	}

	public HierarchicalClause getHierarchicalClause() {
		return hierarchicalClause;
	}

	public Subquery getSubquery() {
		return subquery;
	}
}
